#pragma once

namespace My {

// ChangeValueAction

template <typename T, typename A>
ChangeValueAction<T, A>::ChangeValueAction(const ValueType & v, const String & s, const AccessType & a)
	: AccessType(a), m_Value(v), m_Caption(s)
{ 
}
	
template <typename T, typename A>
String ChangeValueAction<T, A>::GetCaption() const
{
	return m_Caption; 
}
	
template <typename T, typename A>
bool ChangeValueAction<T, A>::Execute() 
{
	m_Old = Get();
	Set(m_Value);
	return Get() != m_Old;
}

template <typename T, typename A>
void ChangeValueAction<T, A>::Unexecute() 
{
	Set(m_Old);
}

template <typename T, typename A>
void ChangeValueAction<T, A>::Reexecute()
{
	Set(m_Value);
}

// ObjectValueAccess

template <typename C, typename T>
ObjectValueAccess<C, T>::ObjectValueAccess(ClassType & o, GetType g, SetType s)
	: m_Object(o), m_Get(g), m_Set(s)
{
}
	
template <typename C, typename T>
T ObjectValueAccess<C, T>::Get() const
{
	return (m_Object.* m_Get)();
}
	
template <typename C, typename T>
void ObjectValueAccess<C, T>::Set(T v)
{
	(m_Object.* m_Set)(v);
}

// ObjectRefAccess

template <typename C, typename T>
ObjectRefAccess<C, T>::ObjectRefAccess(ClassType & o, GetType g, SetType s)
	: m_Object(o), m_Get(g), m_Set(s)
{
}

template <typename C, typename T>
const T & ObjectRefAccess<C, T>::Get() const
{
	return (m_Object.* m_Get)();
}

template <typename C, typename T>
void ObjectRefAccess<C, T>::Set(const T & v)
{
	(m_Object.* m_Set)(v);
}

// CreateChangeValue

template <class C, class T>
Action * CreateChangeValue(
	C & object, 
	T (C::* get)() const, 
	void (C::* set)(T), 
	const T & value, 
	const String & caption)
{
	return new ChangeValueAction<T, ObjectValueAccess<C, T> > (value, caption,
		ObjectValueAccess<C, T>(object, get, set));
}

template <class C, class T>
Action * CreateChangeValue(
	C & object, 
	const T & (C::* get)() const, 
	void (C::* set)(const T &), 
	const T & value, 
	const String & caption)
{
	return new ChangeValueAction<T, ObjectRefAccess<C, T> > (value, caption,
		ObjectRefAccess<C, T>(object, get, set));
}

// ChangeValue

template <class C, class T>
void ChangeValue(
	C & object, 
	T (C::* get)() const, 
	void (C::* set)(T), 
	const T & value, 
	const String & caption)
{
	Perform(CreateChangeValue<C, T>(object, get, set, value, caption));
}

template <class C, class T>
void ChangeValue(
	C & object, 
	const T & (C::* get)() const, 
	void (C::* set)(const T &), 
	const T & value, 
	const String & caption)
{
	Perform(CreateChangeValue<C, T>(object, get, set, value, caption));
}


} // My
